#include "esp_jtag_main.h"

/*
 * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
 * SPDX-License-Identifier: Apache-2.0
 */

#include <stdlib.h>
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "usbd_core.h"
#include "usbd_msc.h"
#include "esp_jtag_main.h"
#include "esp_jtag_vendord.h"
#include "tusb_residual.h"
#include "esp_mac.h"
#include "msc.h"
#include "serial.h"
#include "usb_public.h"
#include "usbd_msc.c"
static const char *TAG = "esp_jtag_main"; // 日志标签

#define ESP_JTAG__DESCRIPTOR_LEN (9 + 7 + 7)
#define JTAG_USB_CONFIG_SIZE     (9 + MSC_DESCRIPTOR_LEN + ESP_JTAG__DESCRIPTOR_LEN)

#define MAC_BYTES 6 // MAC地址字节数

static char serial_descriptor[MAC_BYTES * 2 + 1] = { '\0' }; // 序列号描述符(每个字节用2个字符表示+'\0')
/*
    ESP内置JTAG子类和协议分别是0xFF和0x01。
    但是TinyUSB默认值是0x00。
    为了在不修改TinyUSB的情况下使用相同的协议，我们在这里重新定义厂商描述符。
*/
// 接口号、字符串索引、输出端点地址、输入端点地址、端点大小
#define TUD_VENDOR_EUB_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize)                                                                                 \
    /* 接口描述符 */                                                                                                                                         \
    9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_VENDOR_SPECIFIC, EUB_VENDORD_IFACE_SUBCLASS, EUB_VENDORD_IFACE_PROTOCOL, _stridx, /* 输出端点描述符 */ \
        7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,                                                       /* 输入端点描述符 */ \
        7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0

// static const uint8_t esp_jtag_device_descriptor[] = {
//     USB_DEVICE_DESCRIPTOR_INIT(USB_2_1, 0xEF, 0x02, 0x01, BRIDGE_USB_VID, BRIDGE_USB_PID, 0x0200, 0x01),
// };
// static const uint8_t esp_jtag_device_quality_descriptor[] = {
//     USB_DEVICE_QUALIFIER_DESCRIPTOR_INIT(USB_2_1, 0xEF, 0x02, 0x01, 0x01),
// };
static const uint8_t esp_jtag_config_descriptor[] = {
    // 配置描述符
    USB_CONFIG_DESCRIPTOR_INIT(JTAG_USB_CONFIG_SIZE, JTAG_USB_INF_NUM, 0x01, USB_CONFIG_BUS_POWERED, 300),
    // 厂商自定义接口描述符(接口号、字符串索引、输出端点地址、输入端点地址、端点大小)
    TUD_VENDOR_EUB_DESCRIPTOR(0, 4, ESP_JTAG_OUT_EP, ESP_JTAG_IN_EP, 64),
    //(接口号、输出端点地址、输入端点地址、端点大小,字符串索引)
    MSC_DESCRIPTOR_INIT(0x01, ESP_MSC_OUT_EP, ESP_MSC_IN_EP, MSC_MAX_MPS, 0x05),
};

char *esp_jtag_string_descriptors[] = {
    (char[]){ 0x09, 0x04 }, // 0: 支持的语言(英语0x0409)
    "MIDUO",                      // 1: 制造商字符串
    "ESP USB Bridge" ,             // 2: 产品名称
    serial_descriptor,            // 3: 序列号
    "JTAG",                       // 4: 调试接口名称(JTAG或CMSIS-DAP)
    "MSC",                        // 5: MSC接口名称
};

// static const uint8_t esp_jtag_device_quality_descriptor[] = {
//     //0xEF专为复合设备 设计需配合 IAD 描述符使用，兼容性更好（Windows / Linux 无需额外驱动
//     //0x00通常用于复合设备，类信息由接口描述符（bInterfaceClass）单独定义
//     USB_DEVICE_QUALIFIER_DESCRIPTOR_INIT(USB_2_1, 0xEF, 0x02, 0x01, 0x01),
// };

// __WEAK const uint8_t *esp_jtag_device_descriptor_callback(uint8_t speed)
// {
//     (void)speed;
//     return esp_jtag_device_descriptor;
// }

const uint8_t *esp_jtag_config_descriptor_callback(uint8_t speed)
{
    (void)speed;
    return esp_jtag_config_descriptor;
}

// __WEAK const uint8_t *esp_jtag_device_quality_descriptor_callback(uint8_t speed)
// {
//     (void)speed;
//     return esp_jtag_device_quality_descriptor;
// }
__WEAK const uint8_t *esp_jtag_other_speed_config_descriptor_callback(uint8_t speed)
{
    (void)speed;
    //无其他速率配置描述符
    //主要用于 USB 高速（High-Speed）设备 在 全速（Full-Speed）或低速（Low-Speed）模式 下的兼容性配置
    return esp_jtag_config_descriptor;
}
__WEAK const char *esp_jtag_string_descriptor_callback(uint8_t speed, uint8_t index)
{
    (void)speed;

    if (index >= (sizeof(esp_jtag_string_descriptors) / sizeof(char *))) {
        return NULL;
    }
    return esp_jtag_string_descriptors[index];
}

// USB 描述符配置结构体
const struct usb_descriptor esp_jtag_cmsisdap_descriptor = {
    // 设备描述符回调函数（获取设备的基本信息，如VID、PID、设备类等）
    .device_descriptor_callback = usb_device_descriptor_callback_default,
    // 配置描述符回调函数（定义USB设备的配置、接口、端点等）
    .config_descriptor_callback = esp_jtag_config_descriptor_callback,
    // 设备品质描述符回调函数（可选，用于返回设备品质描述符）
    .device_quality_descriptor_callback = usb_device_quality_descriptor_callback_default,
    // 其他速率配置描述符回调函数（用于USB高速/全速/低速兼容性描述）
    .other_speed_descriptor_callback = esp_jtag_other_speed_config_descriptor_callback,
    // 字符串描述符回调函数（返回厂商、产品、序列号等字符串信息）
    .string_descriptor_callback = esp_jtag_string_descriptor_callback,
    // BOS（Binary Device Object Store）描述符（用于USB 2.1+，支持扩展能力描述）
    .bos_descriptor = &bos_desc,
    // Microsoft OS 2.0描述符（用于Windows兼容性，如自动加载驱动）
    .msosv2_descriptor = &msosv2_desc,
};

// 初始化序列号(基于MAC地址)
static void init_serial_no(void)
{
    uint8_t m[MAC_BYTES] = { 0 };
    esp_err_t ret = esp_efuse_mac_get_default(m); // 读取默认MAC地址

    if (ret != ESP_OK) {
        ESP_LOGD(TAG, "Cannot read MAC address and set the device serial number");
    }

    // 将MAC地址转换为字符串格式的序列号
    snprintf(serial_descriptor, sizeof(serial_descriptor),
             "%02X%02X%02X%02X%02X%02X", m[0], m[1], m[2], m[3], m[4], m[5]);
}

int esp_jtag_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
    ESP_LOGI(TAG, "call esp_jtag_class_interface_request_handler\n");
    return 0;
}
int esp_jtag_vendor_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
    int esp_usb_jtag_debug_probe_control_handler(uint8_t busid, struct usb_setup_packet *setup);
    // 处理厂商自定义请求
    return esp_usb_jtag_debug_probe_control_handler(busid, setup);
}

struct usbd_interface *usbd_esp_jtag_init_intf(uint8_t busid, struct usbd_interface *intf)
{
    (void)busid;

    intf->class_interface_handler = esp_jtag_class_interface_request_handler;
    intf->class_endpoint_handler = NULL;
    intf->vendor_handler = esp_jtag_vendor_handler;
    intf->notify_handler = NULL;

    return intf;
}

//usb接口
static struct usbd_interface esp_jtag_intf;
static struct usbd_interface msc_uf2_intf;

/*在esp_jtag_vendord.c中实现端点回调函数*/
struct usbd_endpoint esp_jtag_out_ep = {
    .ep_addr = ESP_JTAG_OUT_EP,
    .ep_cb = esp_jtag_out_callback
};
struct usbd_endpoint esp_jtag_in_ep = {
    .ep_addr = ESP_JTAG_IN_EP,
    .ep_cb = esp_jtag_in_callback
};
// 初始化esp_jtag usb
void esp_jtag_init(uint8_t busid, uint32_t reg_base)
{
    init_serial_no(); // 初始化序列号

    usbd_desc_register(busid, &esp_jtag_cmsisdap_descriptor);
    /*!< esp_jtag */
    usbd_add_interface(0, usbd_esp_jtag_init_intf(0, &esp_jtag_intf));
    usbd_add_endpoint(0, &esp_jtag_out_ep);
    usbd_add_endpoint(0, &esp_jtag_in_ep);
    //todo msc
    /*!< msc */
    usbd_add_interface(busid, usbd_msc_init_intf(busid, &msc_uf2_intf, ESP_MSC_OUT_EP, ESP_MSC_IN_EP));
    extern void usbd_event_handler(uint8_t busid, uint8_t event);
    // usbd_event_handler在dap.main.c中定义
    usbd_initialize(busid, reg_base, usbd_event_handler);

    // 初始化各功能模块
    serial_init(); // 初始化串口功能
    msc_init();    // 初始化Mass Storage功能

    void eub_debug_probe_init(void);
    void eub_vendord_start(void);
    eub_vendord_start();    // 启动厂商自定义功能
    eub_debug_probe_init(); // 初始化调试探针

}
/*
 *usb配置成功后回调函数   
*/
void usbjtag_usbd_event_cfg(void)
{
    //开启第一次读usb-jtag数据，在usb配置成功后
    start_first_usbjtag_read();
    // void eub_vendord_start(void);
    // eub_vendord_start();  // 启动厂商自定义功能
    //eub_debug_probe_init(); // 初始化调试探针
}
/* JTAG反初始化函数 */
void esp_usb_jtag_deinit(void);
/*
 * 反初始化esp-uf2-jtag   
*/
void esp_jtag_deinit(uint8_t busid)
{
    //
    usbd_deinitialize(busid);
    serial_deinit();
    usb_esp_jtag_serial_enable(); // 启用JTAG串口

    eub_vendord_stop();    // 停止厂商自定义功能
    esp_usb_jtag_deinit(); // 反初始化esp-uf2-jtag
}
